package com.xianyun.smartpicturebackend.manager;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RandomUtil;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.model.ciModel.persistence.ImageInfo;
import com.xianyun.smartpicturebackend.config.COSClientConfig;
import com.xianyun.smartpicturebackend.exception.ErrorCode;
import com.xianyun.smartpicturebackend.exception.ThrowUtils;
import com.xianyun.smartpicturebackend.model.dto.file.UploadPictureResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;


/**
 * @author xianYun
 * @version 1.0
 **/
@Slf4j
@Service
public class FileManage {
    @Resource
    private COSClientConfig cosClientConfig;

    @Resource
    private CosManage cosManage;

    /**
     * 上传图片
     *
     * @param multipartFile
     * @param uploadPathPrefix 上传路径的前缀
     * @return
     */
    public UploadPictureResult uploadPicture(MultipartFile multipartFile, String uploadPathPrefix) {
        //1. 校验图片
        validPicture(multipartFile);
        //2. 拼接上传路径
        //图片名称格式：时间戳+uuid+.后缀名
        String uuid = RandomUtil.randomString(16);
        String originalFilename = multipartFile.getOriginalFilename();
        //重新生成图片名称
        String uploadFileName = String.format("%s_%s.%s", DateUtil.formatDate(new Date()),
                uuid, FileUtil.getSuffix(originalFilename));
        //将前缀
        String uploadPath = String.format("/%s/%s", uploadPathPrefix, uploadFileName);
        //3. 创建临时文件
        File tempFile = null;
        try {
            tempFile = File.createTempFile(uploadPathPrefix, null);
            multipartFile.transferTo(tempFile);
            //4. 上传图片
            PutObjectResult putObjectResult = cosManage.putPictureObject(uploadPath, tempFile);
            //5. 包装返回图片的信息
            //从上传结果中获取图片的基本你返回信息
            ImageInfo imageInfo = putObjectResult.getCiUploadResult().getOriginalInfo().getImageInfo();
            //将返回的信息封装到自定义返回数据对象中
            //计算宽高比
            double picScale = imageInfo.getWidth() * 1.0 / imageInfo.getHeight();
            UploadPictureResult uploadPictureResult = new UploadPictureResult();
            uploadPictureResult.setUrl(cosClientConfig.getHost() + "/" + uploadPath);
            uploadPictureResult.setThumbnailUrl(null);
            uploadPictureResult.setPicName(FileUtil.mainName(originalFilename));
            uploadPictureResult.setPicSize(multipartFile.getSize());
            uploadPictureResult.setPicWidth(imageInfo.getWidth());
            uploadPictureResult.setPicHeight(imageInfo.getHeight());
            uploadPictureResult.setPicScale(picScale);
            uploadPictureResult.setPicFormat(imageInfo.getFormat());
            uploadPictureResult.setPicColor(null);

            return uploadPictureResult;

        } catch (IOException e) {
            log.error("图片上传到对象存储失败", e);
            throw new RuntimeException(e);
        } finally {
            if (tempFile != null) {
                this.deleteTempPicture(tempFile);
            }
        }
    }

    /**
     * 校验图片，如果不合格则抛出异常
     *
     * @param multipartFile 上传的图片
     */
    protected void validPicture(MultipartFile multipartFile) {
        ThrowUtils.throwIf(multipartFile.isEmpty(),
                ErrorCode.PARAMS_ERROR, "上传图片不能为空");
        long fileSize = multipartFile.getSize();
        //1. 校验文件大小
        ThrowUtils.throwIf(fileSize > 1024 * 1024 * 5,
                ErrorCode.PARAMS_ERROR, "上传图片大小不能超过5M");
        //2. 校验文件类型
        //将支持的文件类型放到一个集合中
        final List<String> supportType = Arrays.asList("jpeg", "png", "jpg", "webp");
        String suffix = FileUtil.getSuffix(multipartFile.getOriginalFilename());
        ThrowUtils.throwIf(!supportType.contains(suffix),
                ErrorCode.PARAMS_ERROR, "上传图片格式不支持");
    }

    protected void deleteTempPicture(File file) {
        if (file == null) {
            return;
        }
        boolean deleteRes = file.delete();
        if (!deleteRes){
            log.error("deleteTempPicture failed, filePath：{}", file.getAbsolutePath());
        }

    }
}


